﻿using Net8.Project.Model.Tenants;
using SqlSugar;
using System.Reflection;

namespace Net8.Project.Common.DB
{
    /// <summary>
    /// 租户工具类，提供多租户相关的实体类型、表名、连接配置等操作辅助方法。
    /// </summary>
    public static class TenantUtil
    {
        /// <summary>
        /// 获取所有多租户实体类型（可按租户隔离类型筛选）。
        /// </summary>
        /// <param name="tenantType">租户隔离类型（可选）</param>
        /// <returns>多租户实体类型列表</returns>
        public static List<Type> GetTenantEntityTypes(TenantTypeEnum? tenantType = null)
        {
            return SqlsugarSetup.Entitys
                .Where(u => u.IsClass && !u.IsInterface && !u.IsAbstract)
                .Where(s => IsTenantEntity(s, tenantType))
                .ToList();
        }

        /// <summary>
        /// 判断类型是否为多租户实体（可按租户隔离类型筛选）。
        /// </summary>
        /// <param name="u">类型</param>
        /// <param name="tenantType">租户隔离类型（可选）</param>
        /// <returns>是多租户实体返回true，否则false</returns>
        public static bool IsTenantEntity(this Type u, TenantTypeEnum? tenantType = null)
        {
            var mta = u.GetCustomAttribute<MultiTenantAttribute>();
            if (mta is null)
                return false;

            if (tenantType != null && mta.TenantType != tenantType)
                return false;

            return true;
        }

        /// <summary>
        /// 获取指定类型的租户表名（表隔离场景下）。
        /// </summary>
        /// <param name="type">实体类型</param>
        /// <param name="db">SqlSugar客户端</param>
        /// <param name="id">租户唯一标识</param>
        /// <returns>租户表名</returns>
        public static string GetTenantTableName(this Type type, ISqlSugarClient db, string id)
        {
            var entityInfo = db.EntityMaintenance.GetEntityInfo(type);
            return $"{entityInfo.DbTableName}_{id}";
        }

        /// <summary>
        /// 批量设置表隔离下所有多租户实体的表名映射。
        /// </summary>
        /// <param name="db">SqlSugar客户端</param>
        /// <param name="id">租户唯一标识</param>
        public static void SetTenantTable(this ISqlSugarClient db, string id)
        {
            var types = GetTenantEntityTypes(TenantTypeEnum.Tables);
            foreach (var type in types)
            {
                db.MappingTables.Add(type.Name, type.GetTenantTableName(db, id));
            }
        }

        /// <summary>
        /// 根据租户信息生成数据库连接配置（ConnectionConfig）。
        /// </summary>
        /// <param name="tenant">租户实体</param>
        /// <returns>数据库连接配置</returns>
        /// <exception cref="ArgumentException">DbType 为空时抛出</exception>
        public static ConnectionConfig GetConnectionConfig(this SysTenant tenant)
        {
            if (tenant.DbType is null)
                throw new ArgumentException("Tenant DbType Must");

            return new ConnectionConfig()
            {
                ConfigId = tenant.ConfigId,
                DbType = tenant.DbType.Value,
                ConnectionString = tenant.Connection,
                IsAutoCloseConnection = true,
                MoreSettings = new ConnMoreSettings()
                {
                    IsAutoRemoveDataCache = true,
                    SqlServerCodeFirstNvarchar = true,
                },
            };
        }
    }
}
